package com.tools.demo.login.secret;



import com.tools.demo.login.secret.exception.RsaException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * RSA私钥对象
 * @author Haviven
 * @since 2021/9/16
 **/
public class RsaPrivateKey implements RsaEncode {

    private final PrivateKey privateKey;

    /**
     * 指定privateKey创建RSAPrivateKey对象
     * @param privateKey privateKey
     */
    public RsaPrivateKey(PrivateKey privateKey) {
        this.privateKey = privateKey;
    }

    /**
     * 指定privateKey字符串创建RSAPrivateKey对象
     * @param privateKey privateKey
     */
    public RsaPrivateKey(String privateKey) {
        try {
            byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            this.privateKey = keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 加密
     * @param content 被加密内容
     * @return 加密内容
     */
    @Override
    public byte[] encrypt(byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 加密
     * @param content 被加密内容
     * @return 加密内容
     */
    @Override
    public String encrypt(String content) {
        try {
            return new String(Base64.getEncoder().encode(encrypt(content.getBytes(RsaEncode.CHARSET))));
        } catch (UnsupportedEncodingException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 解密
     * @param content 被解密内容
     * @return 解密内容
     */
    @Override
    public byte[] decrypt(byte[] content) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 解密
     * @param content 被解密内容
     * @return 解密内容
     */
    @Override
    public String decrypt(String content) {
        try {
            return new String(decrypt(Base64.getDecoder().decode(content)), RsaEncode.CHARSET);
        } catch (UnsupportedEncodingException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 签名
     * @param content 被签名内容
     * @return 签名数组
     */
    public byte[] sign(byte[] content) {
        try {
            Signature signature = Signature.getInstance(RsaEncode.SIGNATURE_INSTANCE);
            signature.initSign(privateKey);
            signature.update(content);
            return signature.sign();
        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 签名
     * @param content 被签名内容
     * @return 签名字符串
     */
    public String sign(String content){
        try {
            return new String(Base64.getEncoder().encode(sign(content.getBytes(RsaEncode.CHARSET))), RsaEncode.CHARSET);
        } catch (UnsupportedEncodingException e) {
            throw new RsaException(e);
        }
    }

    /**
     * 获取PrivateKey
     * @return PrivateKey
     */
    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    /**
     * 获取PrivateKey密钥
     * @return privateKey密钥
     */
    @Override
    public String getKey() {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }
}
